package com.hujing.springsource.a39;

import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.boot.*;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext;
import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebApplicationContext;
import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.annotation.*;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.io.ClassPathResource;

import java.util.Arrays;

public class A39_3 {

    @SuppressWarnings("all")
    public static void main(String[] args) throws Exception {
        SpringApplication app = new SpringApplication();
        //添加初始化器
        app.addInitializers(applicationContext -> System.out.println("执行初始化器增强..."));

        System.out.println(">>>>>>>>2.封装启动 args");
        DefaultApplicationArguments applicationArguments = new DefaultApplicationArguments(args);

        System.out.println(">>>>>>>>8.创建容器");
        GenericApplicationContext context = createApplicationContext(WebApplicationType.SERVLET);
        System.out.println(">>>>>>>>9.准备容器");
        for (ApplicationContextInitializer initializer : app.getInitializers()) {
            initializer.initialize(context);
        }
        System.out.println(">>>>>>>>10.加载bean定义");
        //1.加载配置类中的bean定义
        DefaultListableBeanFactory beanFactory = context.getDefaultListableBeanFactory();
        AnnotatedBeanDefinitionReader reader1 = new AnnotatedBeanDefinitionReader(beanFactory);
        reader1.register(Config.class);
        //2.加载xml中的bean定义
        XmlBeanDefinitionReader reader2 = new XmlBeanDefinitionReader(beanFactory);
        reader2.loadBeanDefinitions(new ClassPathResource("b03.xml"));
        //3.通过扫描加载bean的定义
        ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(beanFactory);
        scanner.scan("com.hujing.springsource.a39.sub");

        System.out.println(">>>>>>>>11.refresh容器");
        context.refresh();

        for (String name : context.getBeanDefinitionNames()) {
            System.out.println("name:"+name+" 来源:"+context.getBeanFactory().getBeanDefinition(name).getResourceDescription());
        }

        System.out.println(">>>>>>>>12.执行runner方法");
        for (CommandLineRunner runner : context.getBeansOfType(CommandLineRunner.class).values()) {
            runner.run(args);
        }
        for (ApplicationRunner runner : context.getBeansOfType(ApplicationRunner.class).values()) {
            runner.run(applicationArguments);
        }
    }

    //创建容器
    private static GenericApplicationContext createApplicationContext(WebApplicationType type) {
        switch (type) {
            case SERVLET:
                return new AnnotationConfigServletWebApplicationContext();
            case REACTIVE:
                return new AnnotationConfigReactiveWebServerApplicationContext();
            default:
                return new AnnotationConfigApplicationContext();
        }
    }

    static class Bean3{}

    static class Bean5{}

    @Configuration
    static class Config{
        @Bean
        public Bean5 bean5(){
            return new Bean5();
        }

        @Bean
        public ServletWebServerFactory servletWebServerFactory(){
            return new TomcatServletWebServerFactory();
        }

        @Bean
        public CommandLineRunner commandLineRunner(){
            return new CommandLineRunner() {
                @Override
                public void run(String... args) throws Exception {
                    System.out.println("执行CommandLineRunner..."+ Arrays.toString(args));
                }
            };
        }

        @Bean
        public ApplicationRunner applicationRunner(){
            return new ApplicationRunner() {
                @Override
                public void run(ApplicationArguments args) throws Exception {
                    System.out.println("执行ApplicationRunner..."+Arrays.toString(args.getSourceArgs()));
                }
            };
        }
    }
}
